#include "LogFlush.h"
#include "Util.h"

namespace mylog
{

    LogFlush::LogFlush()
        : g_conf_data(Util::JsonData::GetJsonData())
    {
    }

    void StdoutFlush::flush(const char* data, size_t len)
    {
        std::cout.write(data, len);
    }

    FileFlush::FileFlush(const std::string& filename)
        : filename_(filename)
    {
        // 创建所给文件夹，保证文件可以在给定路径中被创建
        Util::File::CreateDirectory(Util::File::Path(filename));
        // 打开文件
        fs_ = fopen(filename.c_str(), "ab");
        if (fs_ == NULL)
        {
            std::cerr << __FILE__ << ":" << __LINE__ << " open log file failed\n";
            perror(NULL);
        }
    }


    void FileFlush::flush(const char* data, size_t len)
    {
        fwrite(data, 1, len, fs_);
        if (ferror(fs_))
        {
            std::cerr << __FILE__ << ":" << __LINE__ << " write log file failed\n";
            perror(NULL);
        }
        if (g_conf_data->flush_log == 1)
        {
            std::cerr << __FILE__ << ":" << __LINE__ << " fflush file failed\n";
            perror(NULL);
        }
        else if (g_conf_data->flush_log == 2)
        {
            fflush(fs_);
            fsync(fileno(fs_));
        }
    }

    RollFileFlush::RollFileFlush(const std::string &filename, size_t max_size)
        : max_size_(max_size), basename_(filename)
    {
        Util::File::CreateDirectory(Util::File::Path(filename));
    }

    void RollFileFlush::flush(const char *data, size_t len)
    {
        // 确认文件大小不满足滚动需求
        InitLogFile();
        // 向文件写入内容
        fwrite(data, 1, len, fs_);
        if(ferror(fs_)){
            std::cout <<__FILE__<<__LINE__<<"write log file failed"<< std::endl;
            perror(NULL);
        }
        cur_size_ += len;
        if(g_conf_data->flush_log == 1){
            if(fflush(fs_)){
                std::cout <<__FILE__<<__LINE__<<"fflush file failed"<< std::endl;
                perror(NULL);
            }
        }else if(g_conf_data->flush_log == 2){
            fflush(fs_);
            fsync(fileno(fs_));
        }
    }


    void RollFileFlush::InitLogFile()
    {
        if (fs_==NULL || cur_size_ >= max_size_)
        {
            if(fs_!=NULL){
                fclose(fs_);
                fs_=NULL;
            }   
            std::string filename = CreateFilename();
            fs_=fopen(filename.c_str(), "ab");
            if(fs_==NULL){
                std::cout <<__FILE__<<__LINE__<<"open file failed"<< std::endl;
                perror(NULL);
            }
            cur_size_ = 0;
        }
    }


    std::string RollFileFlush::CreateFilename()
    {
        time_t time_ = Util::Date::Now();
        struct tm t;
        localtime_r(&time_, &t);
        std::string filename = basename_;
        filename += std::to_string(t.tm_year + 1900);
        filename += std::to_string(t.tm_mon + 1);
        filename += std::to_string(t.tm_mday);
        filename += std::to_string(t.tm_hour + 1);
        filename += std::to_string(t.tm_min + 1);
        filename += std::to_string(t.tm_sec + 1) + '-' +
                    std::to_string(cnt_++) + ".log";
        return filename;
    }
} // namespace mylog